package mirabilis.org;

import java.util.ArrayList;
import java.util.ListIterator;

import random.CommonState;

import mirabilis.org.config.Configuration;
import mirabilis.org.simplices.Coordinates;
import mirabilis.org.simplices.Vertex;
import mirabilis.samples.cec2014.Cec2014;



public abstract class GradientSimplex extends Thread{
	
	public static void main(String[] args) {
		Configuration.F=2;
		Configuration.N=2;
		Configuration.upper_bound= 100;
		Configuration.lower_bound= -100;	
		Cec2014 bench = new Cec2014();
		
		
		double scaleratio = (Configuration.upper_bound - Configuration.lower_bound);
		double radius = Math.sqrt(((Configuration.upper_bound - Configuration.lower_bound)*(Configuration.upper_bound - Configuration.lower_bound)/2.0));
		

		
		
		for(int i=0;i<100;i++){
			double p1x = CommonState.r.nextDouble()*scaleratio+Configuration.lower_bound;
			double p1y = CommonState.r.nextDouble()*scaleratio+Configuration.lower_bound;
			
			double p2x = CommonState.r.nextDouble()*scaleratio+Configuration.lower_bound;
			double p2y = CommonState.r.nextDouble()*scaleratio+Configuration.lower_bound;

			double p3x = CommonState.r.nextDouble()*scaleratio+Configuration.lower_bound;
			double p3y = CommonState.r.nextDouble()*scaleratio+Configuration.lower_bound;

					
			double[] genes = {p1x,p1y};
			double fp1 = bench.evaluate(genes); 
			
			double[] genes2 = {p2x,p2y};
			double fp2 = bench.evaluate(genes2); 
			
			double[] genes3 = {p3x,p3y};
			double fp3 = bench.evaluate(genes3); 
			
			double [] p1 = {p1x,p1y,fp1};
			double [] p2 = {p2x,p2y,fp2};
			double [] p3 = {p3x,p3y,fp3};
			
			double [] grad = unit_gradient(p1, p2, p3);
			
			if (fp1<=fp2 && fp1<=fp3)
				System.out.println(p1x+" "+p1y+" "+(p1x-(5*grad[0]))+" "+(p1y-(5*grad[1]))+" "+p2x+" "+p2y+" "+p3x+" "+p3y);
			if (fp2<=fp1 && fp2<=fp3)
				System.out.println(p2x+" "+p2y+" "+(p2x-(5*grad[0]))+" "+(p2y-(5*grad[1]))+" "+p1x+" "+p1y+" "+p3x+" "+p3y);
			if (fp3<=fp1 && fp3<=fp2)
				System.out.println(p3x+" "+p3y+" "+(p3x-(5*grad[0]))+" "+(p3y-(5*grad[1]))+" "+p2x+" "+p2y+" "+p1x+" "+p1y);
			
			//System.out.println(p1x+" "+p1y+" "+(p1x-(grad[0]))+" "+(p1y-(grad[1])));
			
		}
		
	}
	
	public static double[] unit_gradient(double[] p1,double[] p2,double[] p3){
		
		double[] grad = gradient(p1, p2, p3);
		
		double a = Math.pow(grad[0], 2);
		double b = Math.pow(grad[1], 2);
		
		double absolute =	Math.sqrt(a+b);
		double[] unit = new double[grad.length];
		
		unit[0] = grad[0] / absolute;
		unit[1] = grad[1] / absolute;
		
		return unit;
	}
	
	public static double[] gradient(double[] p1,double[] p2,double[] p3){
		
		double [] v1 = new double[p1.length];
		double [] v2 = new double[p1.length];
		
		//cross product
		double [] u = new double[p1.length]; 
		
		for(int i=0;i<v1.length;i++){
			v1[i] = p2[i] - p1[i];
			v2[i] = p3[i] - p1[i];
		}
		
		//v1 x v2
		u[0] = v1[1] * v2[2] - v1[2] * v2[1]; // a
		u[1] = v1[2] * v2[0] - v1[0] * v2[2]; // b
		u[2] = v1[0] * v2[1] - v1[1] * v2[0]; // c
		
		//ecuacion del plano hasta aqui aX + bY + c f(x,y) = 0
		
		//para el gradiente f(x,y) = -a/c X + -b/c Y  
		
		double [] grad = new double[2];
		
		grad[0] = - (u[0] / u[2]);
		grad[1] = - (u[1] / u[2]);
		
		//System.out.println("AA"+grad[0]+" "+grad[1]);
			
		return grad;
	}
}
